package uspeedd.parser;

import java.io.File;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;

import uspeedd.lectureUspeed;
import uspeedd.metamodel.Declaration;
import uspeedd.metamodel.ElementUspeed;
import uspeedd.metamodel.Liens;
import uspeedd.metamodel.enumeration.TypeAssociationUspeed;
import uspeedd.metamodel.enumeration.TypeDeclarationUspeed;
import utils.FichierTexte;

public class Uspeed implements lectureUspeed<ElementUspeed>
{
	private List<ElementUspeed> list = new ArrayList<ElementUspeed>();
	
	@Override
	public List<ElementUspeed> lecture(File file)
	{
		if(file == null || !file.exists()) return null;
		
		this.list = new ArrayList<ElementUspeed>();

		FichierTexte fichier = new FichierTexte(file);
		List<String> listString = fichier.lecture();
		
		if(listString == null) return this.list;
		
		Iterator<String> it = listString.iterator();
		while(it.hasNext())
		{
			ElementUspeed element = new ElementUspeed();
			
			String phrase = it.next();
			char[] maPhrase = phrase.toCharArray();
			
			for(int i = 0; i < maPhrase.length; ++i)
			{
				if(maPhrase[0] == '(')
				{
					//on appelle une fonction dans Liens qui analyse la phrase et 
					//renvoie un objet liens qu'on ajoute dans la liste mesLiens

					element.add(analyseLien(phrase));
				}
				else if(maPhrase[0] == '|'){
					//on appelle une fonction dans Declarations qui analyse la phrase et 
					//renvoie un objet déclarations qu'on ajoute dans la liste mesDeclarations
					element.add(analyseDeclaration(phrase));
				}
			}
		}

		return this.list;
	}
	
	public Liens analyseLien(String association)
	{
		int j;
		Liens lien = new Liens();
		
		//Divise
		String mots[] = association.split("("); //Pour une déclaration type (|nomClasse|to|nomClasse2|) donne: mots{'|nomClasse|to|nomClasse2'}
		String valeurs[] = mots[0].split("|");//mots{'nomClasse','to','nomClasse2'}
		String cardinalite[] = valeurs[1].split(" ");
		
		/* On recherche les deux noms de classe pour voir si ils existent 
		 * Si oui, on les ajoutes, sinon on monte une erreur */
		
		List<Declaration> lesDeclarations = new ArrayList<Declaration>();
		
		if(this.list == null) return null;
		for(int i = 0; i < this.list.size(); ++i)
		{
			if(this.list.get(i).getMesLiens() != null)
			{
				lesDeclarations.addAll(this.list.get(i).getMesDeclarations());
			}
		}
		
		for(j=0; j<lesDeclarations.size(); j++){
					
			if(lesDeclarations.get(j).getNom().equals(valeurs[0])){
				lien.setClasse1(lesDeclarations.get(j));
			}
			else if(lesDeclarations.get(j).getNom().equals(valeurs[1])){
				lien.setClasse1(lesDeclarations.get(j));
			}
			else {
				System.out.println("Erreur de déclarations, vérifier les classes");
			}
			
			/* On analyse valeurs[1] pour connaitre le type d'association */
			if(cardinalite[0] == "to" || cardinalite[1] == "to"){
				lien.setMonLien(TypeAssociationUspeed.ASSOCIATION);
				lien.setCardinalite1("1");
				lien.setCardinalite2("1");
			}
			else if(cardinalite[0] == "+" || cardinalite[1] == "+"){
				lien.setMonLien(TypeAssociationUspeed.NOTE);
				lien.setCardinalite1("1");
				lien.setCardinalite2("1");
			}
			else if(cardinalite[0] == "Herite" || cardinalite[1] == "Herite"){
				lien.setMonLien(TypeAssociationUspeed.INHERITANCE);
				lien.setCardinalite1("1");
				lien.setCardinalite2("1");
			}
			else if(cardinalite[0] == "Use" || cardinalite[1] == "USE"){
				lien.setMonLien(TypeAssociationUspeed.USE);
				lien.setCardinalite1("1");
				lien.setCardinalite2("1");
			}
			else if(cardinalite[0] == "to>" || cardinalite[1] == "to>"){
				lien.setMonLien(TypeAssociationUspeed.AGGREGATION);
				lien.setCardinalite1("1");
				lien.setCardinalite2("1");
			}
			else if(cardinalite[0] == "-to>" || cardinalite[1] == "-to>"){
				lien.setMonLien(TypeAssociationUspeed.COMPOSITION);
				lien.setCardinalite1("1");
				lien.setCardinalite2("1");
			}
			else{
				lien.setCardinalite1(cardinalite[0]);
				lien.setCardinalite2(cardinalite[2]);			
			}
			
		}
		return lien;
	}
	
	/* Fonction permettant de décomposer les phrases, renvoie un objet déclaration */
	public Declaration analyseDeclaration(String laPhrase){
		int j,k;
		Declaration declaration = new Declaration();
		
		//Divise
		
		//String classe = laPhrase.substring(laPhrase.indexOf(":"), laPhrase.indexOf("|"));
		
		String mots[] = laPhrase.split("|"); //Pour une déclaration type |C:nomClasse| donne: mots{'C:nomClasse'}
		String valeurs[] = mots[0].split(":");//mots{'C','nomClasse'}
		
		if(valeurs[0] == "C")
			declaration.setType(TypeDeclarationUspeed.Classe);
		else if(valeurs[0] == "I")
			declaration.setType(TypeDeclarationUspeed.Interface);
		else if(valeurs[0] == "A")
			declaration.setType(TypeDeclarationUspeed.Attributs);
		else if(valeurs[0] == "M")
			declaration.setType(TypeDeclarationUspeed.Methode);
		
		declaration.setNom(valeurs[1]);
		
		for(j=2; j<valeurs.length; j++){
			String mesPhrases[] = valeurs[j].split(";");
			for(k=0;k<mesPhrases.length; k++)
				declaration.add(mesPhrases[k]);
		}
	
		return declaration;
	}
}
